#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

// int main()
// {
//     int* p = nullptr;
//     *p = 10;
//     std::cout << getpid() << std::endl;
//     // int a = 10;
//     // a /= 0;
//     return 0;
// }

// int Sum(int start, int end)
// {
//     int sum = 0;
//     for (int i = start; i <= end; i++)
//     {
//         sum /= 0; // 除零错误
//         sum += i;
//     }
//     return sum;
// }

// int main()
// {
//     // int total = Sum(0, 100);
//     // std::cout << "total = " << total << std::endl;

//     pid_t id = fork();
//     if (id == 0)
//     {
//         // child
//         sleep(1);
//         int total = Sum(0, 100);
//         std::cout << "total = " << total << std::endl;
//         exit(1);
//     }
//     // father
//     int status = 0;
//     int rid = waitpid(id, &status, 0);
//     if (rid > 0)
//     {
//         printf("exit code: %d, exit sig: %d, core dump: %d\n",
//                (status >> 8) & 0xFF, status & 0x7F, (status >> 7) & 0x1);
//     }
//     return 0;
// }

// int main()
// {
//     // sigset_t Linux给用户提供的一个用户级的数据类型, 禁止用户直接修改位图
//     sigset_t bits; 

//     return 0;
// }

void PrintPending(sigset_t& pending)
{
    std::cout << "curr process[" << getpid() << "]pending: ";
    for(int signo = 31;signo >= 1;signo--)
    {
        // 判断signo信号是否在pending中
        if(sigismember(&pending,signo)) 
        {
            std::cout << "1";
        }
        else
        {
            std::cout << "0";
        }
    }
    std::cout << "\n";
}

// 测试在递达之前清零还是递达之后
void handler(int signo)
{
    std::cout << signo << "号信号被递达！！！" << std::endl;
    
    std::cout << "--------------------------" << std::endl;
    sigset_t pending;
    sigpending(&pending);
    PrintPending(pending);
    std::cout << "--------------------------" << std::endl;
}

int main()
{
    // 0.对2号信号自定义捕捉
    signal(2,handler); // 自定义捕捉
    signal(2,SIG_IGN); // 忽略一个信号
    signal(2,SIG_DFL); // 信号的默认处理动作
    // 1.屏蔽2号信号
    sigset_t block_set,old_set;
    sigemptyset(&block_set); // 清空信号集
    sigemptyset(&old_set);
    sigaddset(&block_set,SIGINT); // 屏蔽2号信号，没有修改内核结构
    // 1.1.进入进程的block表
    // 阻塞block_set信号集中的信号，old_set为输出型参数，保存原始信号集
    sigprocmask(SIG_BLOCK,&block_set,&old_set); // 修改当前进行的内核表，完成对2号信号的屏蔽
    
    int cnt = 10;
    while(true)
    {
        // 2.获取当前信号集
        sigset_t pending;
        sigpending(&pending); // 输出型参数

        // 3.打印pending信号集
        PrintPending(pending);
        cnt--;

        // 4.解除对2号信号的屏蔽
        if(cnt == 0)
        {
            std::cout << "解除对2号信号的屏蔽" << std::endl;
            // 解除对old_set信号集的屏蔽，原信号集保存到block_set中
            sigprocmask(SIG_SETMASK,&old_set,&block_set);
        }

        sleep(1);
    }
    return 0;
}